package com.cskaoyan.javase.oop3._0abstract._0introduction;
/**
 * 抽象类的引入
 *
 * 以下猫狗继承案例，是一个非常基础的继承语法的代码。
 * 思考一下Animal类的继承体系，有什么问题吗？
 * 从以下两个角度分析：
 * 从代码角度上，有没有冗余代码？
 *      Animal类的shout其实是没有被调用的
 *      这个shout方法就是为了被子类继承然后重写的
 *      理论上来说,它不需要方法体,方法体是多余的
 *
 * 从设计角度上，在这个案例中，会存在一个动物对象吗？
 *      动物类是作为一个抽象的概念而存在的
 *      它是一个抽象的概念
 *      我们不会用它创建对象
 *      这个类在体系中,就是为了用来继承的,不需要创建对象,它的成员也不会直接被使用,而是被子类继承后使用
 *
 * 于是,我们提出两个改进的方向：
 *      1.Animal类就是作为顶层抽象祖先类而存在的，不需要创建对象，于是干脆不要创建对象了。
 *      2.Animal类当中的shout方法不需要方法体，仅用于作为被继承和重写一个方法声明。
 *
 * 于是:
 * 1.没有方法体的方法必须声明为抽象方法.
 *      抽象方法的声明语法:
 *      [访问权限修饰符] abstract 返回值类型 方法名(形参列表);
 *      抽象方法没有方法体,形参列表后面直接跟一个";".
 *
 * 2.抽象方法必须在一个抽象类中,一个类要么是抽象类,允许存在抽象方法
 *      而一个普通类,不允许存在抽象方法,必须实现所有的方法.
 *      抽象类的声明语法:
 *      [访问权限修饰符] abstract class 类名{
 *          // 类体
 *      }
 *
 * 以上将方法改为抽象方法,类改为抽象类,就实现了我们的需求.
 * 于是:
 *      Animal类就无法创建对象了
 *      shout方法也没有方法体了
 *      继承的体系仍然存在,多态现象也正常发生.
 *
 * @since 14:31
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        // 'Animal' is abstract; cannot be instantiated
        // new Animal();

        Animal a;
        a = new Cat();
        a.shout();
        a = new Dog();
        a.shout();
    }
}

// Class 'Animal' must either be declared abstract or implement abstract method 'shout()' in 'Animal'
abstract class Animal {
    // '{' or ';' expected
    // Missing method body, or declare abstract
    // Abstract method in non-abstract class
    public abstract void shout();
}
class Cat extends Animal {
    @Override
    public void shout() {
        System.out.println("猫叫");
    }
}
class Dog extends Animal {
    @Override
    public void shout() {
        System.out.println("狗叫");
    }
}